/*************************************************************************
 *  Poker.cpp                                                            *
 *                                                                       *
 *  Copyright 2011, Ville Jyrkkä,                                        *
 *  M-Poker team (https://github.com/jykae/M-Poker/wiki)                 *
 *                                                                       *
 *  This file is part of M-Poker.                                        *
 *                                                                       *
 *  M-Poker is free software: you can redistribute it and/or modify      *
 *  it under the terms of the GNU General Public License as              *
 *  published by the Free Software Foundation, either version 3 of the   *
 *  License, or (at your option) any later version.                      *
 *                                                                       *
 *  M-Poker is distributed in the hope that it will be useful,           *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of       *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
 *  GNU General Public License for more details.                         *
 *                                                                       *
 *  You should have received a copy of the GNU General Public            *
 *  License along with M-Poker.                                          *
 *  If not, see <http://www.gnu.org/licenses/>.                          *
 *                                                                       *
 * ***********************************************************************/

#include "poker.h"
#include <QDeclarativeContext>
#include <sstream>
#include <iostream>

using std::stringstream;

Poker::Poker()
{
    money_ = 20;
    bet_ = 1;

    for(int i = 0; i < 52; ++i)
    {
        QString qs;
        qs = "qrc:/images/";
        qs = qs + QString::number(i);
        qs = qs + ".png";
        cardpics.push_back(QUrl(qs));
    }
    init();
}

Poker::~Poker()
{
    delete view;
}

void Poker::init()
{
    view = new QDeclarativeView();

    view->setSource(QUrl("qrc:/qml/main.qml"));
    view->rootContext()->setContextProperty("qml_ui", this);
    view->setResizeMode(QDeclarativeView::SizeRootObjectToView);
    view->showFullScreen();

    viewroot = view->rootObject();
    if(viewroot) {
        viewroot->setProperty("money", money_);
        viewroot->setProperty("bet", bet_);
    }

    betplus = viewroot->findChild<QObject*>("betplus");
    if(betplus) {
        connect(betplus, SIGNAL(buttonPressed()), this, SLOT(betIncrease()));
    }

    betminus = viewroot->findChild<QObject*>("betminus");
    if(betminus) {
        connect(betminus, SIGNAL(buttonPressed()), this, SLOT(betDecrease()));
    }

    dealbutton = viewroot->findChild<QObject*>("dealbutton");
    if(dealbutton) {
        connect(dealbutton, SIGNAL(buttonPressed()), this, SLOT(dealNewHand()));
    }

    quitbutton = viewroot->findChild<QObject*>("quitbutton");
    if(quitbutton) {
        connect(quitbutton, SIGNAL(buttonPressed()), view, SLOT(close()));
    }

    message = viewroot->findChild<QObject*>("message");
}

void Poker::dealNewHand()
{
    if(money_ < 1)
    {
        if(message) {
            message->setProperty("text", "OUT OF MONEY!");
        }
        return;
    }

    int card = 0;
    QString qcard;
    bool flag = false;
    int i = 0;
    while(i < 5) {
        //Randomize hand
        card = rand() % 52;
        for( int j=0; j < 5; ++j)
        {
            if( card == hand_[j] )
            {
                flag = true;
                break;
            }
        }
        if(flag)
        {
            flag = false;
            continue;
        }
        hand_[i] = card;
        qcard = "card";
        qcard = qcard + QString::number(i+1);
        dealCard(i, qcard);
        i += 1;
    }

    placeBet();
    message->setProperty("text", "");
    if(dealbutton) {
        disconnect(dealbutton, SIGNAL(buttonPressed()), this, SLOT(dealNewHand()));
        connect(dealbutton, SIGNAL(buttonPressed()), this, SLOT(dealRound()));
        dealbutton->setProperty("text", "Change");
    }

}

void Poker::dealRound()
{
    int card = 0;
    QString qcard;
    bool flag = false;
    int i = 0;
    while(i < 5) {
        switch (i) {
        case 0:
            qcard = "card1";
            break;
        case 1:
            qcard = "card2";
            break;
        case 2:
            qcard = "card3";
            break;
        case 3:
            qcard = "card4";
            break;
        case 4:
            qcard = "card5";
            break;
        default:
            break;
        }
        cardpoint = viewroot->findChild<QObject*>(qcard);
        if(cardpoint && cardpoint->property("flipped") == false) {
            i += 1;
            continue;
        }
        //Randomize hand
        card = rand() % 52;
        for( int j=0; j < 5; ++j)
        {
            if( card == hand_[j] )
            {
                flag = true;
                break;
            }
        }
        if(flag)
        {
            flag = false;
            continue;
        }
        hand_[i] = card;
        dealCard(i, qcard);
        i += 1;
    }

    evaluateHand();
    if(dealbutton) {
        disconnect(dealbutton, SIGNAL(buttonPressed()), this, SLOT(dealRound()));
        connect(dealbutton, SIGNAL(buttonPressed()), this, SLOT(dealNewHand()));
        dealbutton->setProperty("text", "Deal");
    }

    if(bet_ > money_)
    {
        bet_ = money_;
        viewroot->setProperty("bet", bet_);
    }
}

void Poker::dealCard(int cc, QString qcard)
{
    cardpoint = viewroot->findChild<QObject*>(qcard);

    int card = hand_[cc];

    if(cardpoint) {
        cardpoint->setProperty("disableFlip", false);
        cardpoint->setProperty("card", cardpics.at(card));
        cardpoint->setProperty("flipped", false);
    }
}

void Poker::betIncrease()
{
    if (bet_ < 5 && bet_ < money_)
    {
        viewroot->setProperty("bet", ++bet_);
    }
}

void Poker::betDecrease()
{
    if (bet_ > 1)
    {
        viewroot->setProperty("bet", --bet_);
    }
}

void Poker::placeBet()
{
    money_ -= bet_;
    updateMoney();
}

void Poker::updateMoney()
{
    viewroot->setProperty("money", money_);
}

void Poker::evaluateHand()
{
    int eval = evaluator_.evaluate(hand_);

    if( eval == NOTHING )
            return;

        money_ += PAYOUT[eval][bet_-1];
        updateMoney();

        switch (eval) {
            case ROYAL_FLUSH:
            if(message) {
                message->setProperty("text", "WIN! Royal Flush");
            }
                break;
            case STRAIGHT_FLUSH:
            if(message) {
                message->setProperty("text", "WIN! Straight Flush");
            }
                break;
            case FOUR_KIND:
            if(message) {
                message->setProperty("text", "WIN! Four of Kind");
            }
                break;
            case FULL_HOUSE:
            if(message) {
                message->setProperty("text", "WIN! Full House");
            }
                break;
            case FLUSH:
            if(message) {
                message->setProperty("text", "WIN! Flush");
            }
                break;
            case STRAIGHT:
            if(message) {
                message->setProperty("text", "WIN! Straight");
            }
                break;
            case THREE_KIND:
            if(message) {
                message->setProperty("text", "WIN! Three of Kind");
            }
                break;
            case TWO_PAIR:
            if(message) {
                message->setProperty("text", "WIN! Two Pair");
            }
                break;
            case JACK_BETTER:
            if(message) {
                message->setProperty("text", "WIN! Jacks or Better");
            }
                break;
            default:
                // Shouldn't happen!
                break;
        }
}

